
import { gameHelper } from "../../cccframework/Utils/GameHelpler";
import { recorder } from "../../cccframework/Utils/Recorder";
import eventMgr from "./EventMgr";

export interface Frame {
    index: number
    cmds: Operation[]
}
export interface Operation {
    [key: string]: any;
}
enum ClentState {
    DisConnected,
    Connected,
    Login,
    Ready,
    Matching,
    GameStart,
    GameOver,
}
const ONE_THOUSAND = 1000;
const ws_url: string = 'ws://192.168.1.105:3000';
// const ws_url: string = ''ws://192.168.2.56:3000'';
export default class GameClient {

    private static _instance: GameClient = new GameClient();
    static get instance(): GameClient {
        if (!GameClient._instance) {
            GameClient._instance = new GameClient();
        }
        return GameClient._instance;
    }
    private static _socket: WebSocket = null;
    socket: WebSocket = null
    msgList: Operation[] = [];
    eventList: Event[] = [];
    curState: ClentState = ClentState.DisConnected;
    _token: string = null;
    get token(): string {
        if (!this._token) {
            this._token = recorder.getData('token')
        }
        return this._token;
    }
    set token(v: string) {
        recorder.setData('token', v)
    }
    init() {
        this.connect();
    }


    get curTimeStamp() {
        return new Date().getTime();
    }
    /**连接服务器 */
    connect() {
        let ws = new WebSocket(ws_url, 'game');
        ws.onopen = this.onOpen.bind(this);
        ws.onmessage = this.onReceive.bind(this);
        ws.onerror = this.onError.bind(this);
        ws.onclose = this.onClose.bind(this);
        this.startHeartBeat();
        this.socket = ws;
    }
    /**登录 */
    login() {
        this.send({ type: "login" })
        console.log('正在登录...')
    }
    /**发送消息 */
    send(cmd: Operation) {
        if (this.socket) {
            cmd.token = this.token;
            let msgstr = JSON.stringify(cmd);
            // console.log('this.socket.readyState', this.socket.readyState, WebSocket.CONNECTING, WebSocket.OPEN, WebSocket.CLOSING, WebSocket.CLOSED)
            if (this.socket && this.socket.readyState == WebSocket.OPEN) {
                this.socket.send(msgstr)
            }
        }
        // console.log('发送消息给服务器', msgstr)
    }

    match() {
        this.send({ type: "match" })
        console.log('开始匹配...')
    }
    /**当连接上服务器 */
    onOpen(event: Event) {
        this.curState = ClentState.Connected;
        console.log("已连接上服务器", event);
        // 连接上服务器后就登录
        this.login();
    }
    /**当服务器返回数据 */
    onReceive(event: MessageEvent) {
        let data: Operation;
        // console.log("服务器消息：", event, event.data);
        if (typeof event.data == 'string') {
            data = JSON.parse(event.data);
            // console.log("收到消息消息：", data);
            switch (data.type) {
                case 'loginSuccess':
                    this.token = data.token;
                    this.curState = ClentState.Login;
                    eventMgr.emit(this, 'onLogin')
                    gameHelper.toast('登录成功')
                    console.log("登录成功 账号id为：", data.token);
                    console.log("可以准备匹配了，请点击匹配按钮");
                    break;
                case 'matchSuccess':
                    console.log("匹配成功");
                    eventMgr.emit(this, 'onMatchSuccess')
                    break;
                case 'cmd':
                    // this.applyFrame(data.frame.cmd, data.frame.argv)
                    if (data.frame) {
                        eventMgr.emit(this, 'onUpdate', data.frame)
                    }
                    break
            }
        }
    }
    /**当服务器出错 */
    onError(event) {
        console.error("服务器错误：", event);
        gameHelper.toast('连接出错')
    }
    /**当服务器断开 */
    onClose(event) {
        this.socket.close();
        this.curState = ClentState.DisConnected;
        console.error("与服务器断开连接了，稍后重试", event);
        gameHelper.toast('与服务器断开连接了')
        this.stopHeartBeat();
        setTimeout(() => {
            console.log('正在尝试重连服务器...')
            gameHelper.toast('正在尝试重连服务器...')
            this.connect();
        }, 5 * ONE_THOUSAND)
    }
    cmdList: { [key: string]: any } = {}

    heartBeatTimer: number;
    startHeartBeat() {
        this.heartBeatTimer = setInterval(this.heartBeat.bind(this), 3);
    }
    stopHeartBeat() {
        clearInterval(this.heartBeatTimer)
    }
    heartBeat() {
        this.send({ type: 'heartBeat', time: new Date().getTime() })
    }
    // 定义指令
    defineCmd(cmd: string, func: Function, target: any = this) {
        this.cmdList[cmd] = { func: func, target: target };
    }
    /**应用帧 */
    applyFrame(cmd: string, argv: any[]) {
        this.dispatchCmd(cmd, argv)
    }

    /**派发指令 */
    dispatchCmd(cmd: string, argv: any) {
        let func = this.cmdList[cmd].func;
        let target = this.cmdList[cmd].target;
        func.apply(target, argv)
    }

    seed: number = 5;
    seedRandom() {
        this.seed = (this.seed * 9301 + 49297) % 233280;
        return this.seed / 233280.0;
    }
}

window['gameClient'] = GameClient.instance